package com.kexilo.system.audit.controller;

import com.kexilo.core.audit.domain.SysArchiveConfig;
import com.kexilo.core.audit.domain.SysDataArchive;
import com.kexilo.core.common.annotation.Debounce;
import com.kexilo.core.common.annotation.RateLimiter;
import com.kexilo.core.common.core.page.TableDataInfo;
import com.kexilo.core.common.core.web.BaseController;
import com.kexilo.core.common.core.web.domain.R;
import com.kexilo.system.audit.service.IDataArchiveService;
import com.kexilo.system.audit.service.ISysArchiveConfigService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * 数据归档管理
 *
 * @author Kexilo
 */
@RestController
@RequestMapping("/system/archive")
@Tag(name = "数据归档管理", description = "数据归档相关接口")
public class SysDataArchiveController extends BaseController {
    
    private static final Logger log = LoggerFactory.getLogger(SysDataArchiveController.class);

    @Autowired
    private IDataArchiveService archiveService;

    @Autowired
    private ISysArchiveConfigService configService;

    /**
     * 查询归档记录列表
     */
    @PreAuthorize("@ss.hasPermi('system:archive:list')")
    @GetMapping("/list")
    @Operation(summary = "查询归档记录", description = "分页查询数据归档记录列表")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "查询成功")
    })
    public TableDataInfo list(SysDataArchive archive) {
        startPage();
        List<SysDataArchive> list = archiveService.selectArchiveList(archive);
        return getDataTable(list);
    }

    /**
     * 根据归档记录ID获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:archive:query')")
    @GetMapping("/{archiveId}")
    @Operation(summary = "获取归档记录", description = "根据ID获取归档记录详细信息")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "获取成功")
    })
    public R<SysDataArchive> getInfo(@Parameter(description = "归档记录ID") @PathVariable Long archiveId) {
        return success(archiveService.selectArchiveById(archiveId));
    }

    /**
     * 删除归档记录
     */
    @PreAuthorize("@ss.hasPermi('system:archive:remove')")
    @DeleteMapping("/{archiveIds}")
    @Operation(summary = "删除归档记录", description = "批量删除归档记录")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "删除成功")
    })
    public R<Void> remove(@Parameter(description = "归档记录ID数组") @PathVariable Long[] archiveIds) {
        return toAjax(archiveService.deleteArchiveByIds(archiveIds));
    }

    /**
     * 手动执行归档
     */
    @PreAuthorize("@ss.hasPermi('system:archive:execute')")
    @Debounce(strategy = Debounce.Strategy.USER_METHOD, interval = 10, message = "请勿频繁执行归档操作")
    @PostMapping("/execute/{configId}")
    @Operation(summary = "手动执行归档", description = "手动触发数据归档操作")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "执行成功")
    })
    public R<Long> executeArchive(@Parameter(description = "配置ID") @PathVariable Long configId) {
        try {
            Long archiveId = archiveService.manualArchive(configId);
            return success("归档任务已启动", archiveId);
        } catch (Exception e) {
            log.error("手动执行归档失败", e);
            return R.error("执行失败：" + e.getMessage());
        }
    }

    /**
     * 停止归档任务
     */
    @PreAuthorize("@ss.hasPermi('system:archive:stop')")
    @PostMapping("/stop/{archiveId}")
    @Operation(summary = "停止归档任务", description = "停止正在运行的归档任务")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "停止成功")
    })
    public R<Void> stopArchive(@Parameter(description = "归档记录ID") @PathVariable Long archiveId) {
        boolean stopped = archiveService.stopArchiveTask(archiveId);
        if (stopped) {
            return success("归档任务已停止");
        } else {
            return R.error("停止失败或任务已完成");
        }
    }

    /**
     * 获取归档统计信息
     */
    @PreAuthorize("@ss.hasPermi('system:archive:statistics')")
    @GetMapping("/statistics")
    @Operation(summary = "归档统计", description = "获取归档统计信息")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "获取成功")
    })
    public R<Map<String, Object>> statistics(@Parameter(description = "统计天数") @RequestParam(defaultValue = "7") int days) {
        Map<String, Object> statistics = archiveService.getArchiveStatistics(days);
        return success(statistics);
    }

    /**
     * 验证归档条件
     */
    @PreAuthorize("@ss.hasPermi('system:archive:validate')")
    @PostMapping("/validate")
    @Operation(summary = "验证归档条件", description = "验证归档条件SQL的有效性")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "验证完成")
    })
    public R<Map<String, Object>> validateCondition(
            @Parameter(description = "表名") @RequestParam String tableName,
            @Parameter(description = "归档条件") @RequestParam String condition) {
        Map<String, Object> result = archiveService.validateArchiveCondition(tableName, condition);
        return success(result);
    }

    /**
     * 预览归档数据
     */
    @PreAuthorize("@ss.hasPermi('system:archive:preview')")
    @RateLimiter(key = "archive_preview", limitType = RateLimiter.LimitType.USER, count = 10, time = 60)
    @PostMapping("/preview")
    @Operation(summary = "预览归档数据", description = "预览将要归档的数据")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "预览成功")
    })
    public R<Map<String, Object>> previewData(
            @Parameter(description = "表名") @RequestParam String tableName,
            @Parameter(description = "归档条件") @RequestParam String condition,
            @Parameter(description = "预览数量") @RequestParam(defaultValue = "10") int limit) {
        
        if (limit > 100) {
            return R.error("预览数量不能超过100条");
        }
        
        Map<String, Object> result = archiveService.previewArchiveData(tableName, condition, limit);
        return success(result);
    }

    /**
     * 检查表是否存在
     */
    @PreAuthorize("@ss.hasPermi('system:archive:check')")
    @GetMapping("/checkTable")
    @Operation(summary = "检查表", description = "检查数据表是否存在")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "检查完成")
    })
    public R<Boolean> checkTable(@Parameter(description = "表名") @RequestParam String tableName) {
        boolean exists = archiveService.checkTableExists(tableName);
        return success(exists ? "表存在" : "表不存在", exists);
    }

    // ==================== 归档配置管理 ====================

    /**
     * 查询归档配置列表
     */
    @PreAuthorize("@ss.hasPermi('system:archive:config:list')")
    @GetMapping("/config/list")
    @Operation(summary = "查询归档配置", description = "分页查询归档配置列表")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "查询成功")
    })
    public TableDataInfo configList(SysArchiveConfig config) {
        startPage();
        List<SysArchiveConfig> list = configService.selectConfigList(config);
        return getDataTable(list);
    }

    /**
     * 根据配置ID获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:archive:config:query')")
    @GetMapping("/config/{configId}")
    @Operation(summary = "获取归档配置", description = "根据ID获取归档配置详细信息")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "获取成功")
    })
    public R<SysArchiveConfig> getConfigInfo(@Parameter(description = "配置ID") @PathVariable Long configId) {
        return success(configService.selectConfigById(configId));
    }

    /**
     * 新增归档配置
     */
    @PreAuthorize("@ss.hasPermi('system:archive:config:add')")
    @PostMapping("/config")
    @Operation(summary = "新增归档配置", description = "新增数据归档配置")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "新增成功")
    })
    public R<Void> addConfig(@RequestBody SysArchiveConfig config) {
        if (!configService.checkConfigNameUnique(config).equals("0")) {
            return R.error("新增归档配置失败，配置名称已存在");
        }
        if (!configService.checkTableNameUnique(config).equals("0")) {
            return R.error("新增归档配置失败，表名已存在配置");
        }
        return toAjax(configService.insertConfig(config));
    }

    /**
     * 修改归档配置
     */
    @PreAuthorize("@ss.hasPermi('system:archive:config:edit')")
    @PutMapping("/config")
    @Operation(summary = "修改归档配置", description = "修改数据归档配置")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "修改成功")
    })
    public R<Void> editConfig(@RequestBody SysArchiveConfig config) {
        if (!configService.checkConfigNameUnique(config).equals("0")) {
            return R.error("修改归档配置失败，配置名称已存在");
        }
        if (!configService.checkTableNameUnique(config).equals("0")) {
            return R.error("修改归档配置失败，表名已存在配置");
        }
        return toAjax(configService.updateConfig(config));
    }

    /**
     * 删除归档配置
     */
    @PreAuthorize("@ss.hasPermi('system:archive:config:remove')")
    @DeleteMapping("/config/{configIds}")
    @Operation(summary = "删除归档配置", description = "批量删除归档配置")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "删除成功")
    })
    public R<Void> removeConfig(@Parameter(description = "配置ID数组") @PathVariable Long[] configIds) {
        return toAjax(configService.deleteConfigByIds(configIds));
    }

    /**
     * 状态修改
     */
    @PreAuthorize("@ss.hasPermi('system:archive:config:edit')")
    @PutMapping("/config/changeStatus")
    @Operation(summary = "修改配置状态", description = "启用或禁用归档配置")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "修改成功")
    })
    public R<Void> changeStatus(@RequestBody Map<String, Object> params) {
        Long[] configIds = (Long[]) params.get("configIds");
        String status = (String) params.get("status");
        return toAjax(configService.updateConfigStatus(configIds, status));
    }
}
